/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_comm.c                                                    */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

#include "db2_comm.h"

#define DB2_REPORT_KEY_DBNAME     APM_REPORT_KEY_SESSION".db2.dbname"

#if defined(FRLINUX4) || defined(FRLINUX5)
#define ULLONG_MAX 18446744073709551615ULL
#endif

FR_STATIC uint8_t EBCDIC_TABLE [256] = {
    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
    0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xD5, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
    0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
    0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xE5, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
    0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
    0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
    0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
    0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0x5B, 0xD6, 0xD7,
    0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x5D, 0xE6, 0xE7,
    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
    0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};

/*******************************************************************************
*  FUNC     :  调试用
*  ARGS     :  void
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_dbg(void)
{
    return;
}

/*******************************************************************************
*  FUNC     :  释放内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_free(void **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
    {
        return;
    }

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  释放node函数指针
*  ARGS     :  p_st_node(Frlist_node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    frfree(p_st_node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_value(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_frdata_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Frdata_field *p_st_data = (Frdata_field *)p_st_node->data;
    if (p_st_data->p_field_name)
    {
        frfree(p_st_data->p_field_name);
    }
    if (p_st_data->p_field_value)
    {
        frfree(p_st_data->p_field_value);
    }

    frfree(p_st_node->data);
    p_st_node->data = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_value(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_frdata_free(Frdata_field **pp_st_value)
{
    if (pp_st_value == NULL || *pp_st_value == NULL)
    {
        return;
    }

    Frdata_field *p_st_data = *pp_st_value;
    if (p_st_data->p_field_name)
    {
        frfree(p_st_data->p_field_name);
    }
    if (p_st_data->p_field_value)
    {
        frfree(p_st_data->p_field_value);
    }

    frfree(p_st_data);
    *pp_st_value = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_value(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_cmd_free(Db2_req_cmd **pp_st_cmd)
{
    if (pp_st_cmd == NULL || *pp_st_cmd == NULL)
    {
        return;
    }

    Db2_req_cmd *p_st_cmd = *pp_st_cmd;
    if (p_st_cmd->i_new_flg == DB2_TRUE)
    {
        frdb_statement_free(&p_st_cmd->p_st_statement);
    }

    if (p_st_cmd->p_error_msg)
    {
        frfree(p_st_cmd->p_error_msg);
    }
    frfree(p_st_cmd);
    *pp_st_cmd = NULL;
    return;
}
/*******************************************************************************
*  FUNC     :  Db2_req_cmd节点释放
*  ARGS     :  p_st_node(Frlist_node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_cmd_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Db2_req_cmd *p_st_cmd = (Db2_req_cmd *)p_st_node->data;
    if (p_st_cmd->i_new_flg == DB2_TRUE)
    {
        frdb_statement_free(&p_st_cmd->p_st_statement);
    }
    if (p_st_cmd->p_error_msg)
    {
        frfree(p_st_cmd->p_error_msg);
    }
    frfree(p_st_node->data);
    p_st_node->data = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  做成DB2 request结构
*  RTN      :  非NULL       (normal)
*              NULL         (error)
*  NOTE     :
*******************************************************************************/
L7_req_db2* db2_create_request(void)
{
    L7_req_db2 *p_st_req = NULL;

    /* 申请request */
    p_st_req = (L7_req_db2 *)frmalloc(sizeof(L7_req_db2));
    if (p_st_req == NULL)
    {
        return NULL;
    }

    /* 初始化 */
    memset(p_st_req, 0x0, sizeof(L7_req_db2));
    p_st_req->i_need_req_resp = DB2_REQUEST;
    return p_st_req;
}

/*******************************************************************************
*  FUNC     :  做成DB2 response结构
*  RTN      :  非NULL       (normal)
*              NULL         (error)
*  NOTE     :
*******************************************************************************/
L7_resp_db2* db2_create_response(void)
{
    L7_resp_db2 *p_st_resp = NULL;

    /* 申请request */
    p_st_resp = (L7_resp_db2 *)frmalloc(sizeof(L7_resp_db2));
    if (p_st_resp == NULL)
    {
        return NULL;
    }

    /* 初始化 */
    memset(p_st_resp, 0x0, sizeof(L7_resp_db2));
    return p_st_resp;
}

/*******************************************************************************
*  FUNC     :  初始化分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_init_fragment(L7_fragment_db2 *p_st_fragment)
{
    if (p_st_fragment == NULL)
    {
        return;
    }

    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    memset(p_st_fragment, 0x0, sizeof(L7_fragment_db2));
    p_st_fragment->i_next_correlator = 1;
    p_st_fragment->i_req_resp_flg = DB2_UNKNOW;
    p_st_fragment->i_last_ddm_flg = DB2_FALSE;
    p_st_fragment->i_exter_flg = DB2_FALSE;
    p_st_fragment->i_exter_whole_flg = DB2_FALSE;

    return;
}

/*******************************************************************************
*  FUNC     :  释放分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_destroy_fragment(L7_fragment_db2 **pp_st_fragment)
{
    if (pp_st_fragment == NULL || *pp_st_fragment == NULL)
    {
        return;
    }

    L7_fragment_db2 *p_st_fragment = *pp_st_fragment;
    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    frfree(p_st_fragment);

    *pp_st_fragment = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  session释放
*  ARGS     :  pp_st_session(L7session_db2)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_destroy_session(L7session_db2 **pp_st_session)
{
    if (pp_st_session == NULL || *pp_st_session == NULL)
    {
        return;
    }

    L7session_db2 *p_st_session = *pp_st_session;
    db2_free((void **)&p_st_session->p_cli_host_user);
    db2_free((void **)&p_st_session->p_program);
    db2_free((void **)&p_st_session->p_db_name);
    db2_free((void **)&p_st_session->p_db_user);
    frfree(p_st_session);
    *pp_st_session = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  request信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_destroy_request(L7_req_db2 **pp_st_request)
{
    if(pp_st_request == NULL || *pp_st_request == NULL)
    {
        return;
    }

    L7_req_db2 *p_st_request = *pp_st_request;
    if (p_st_request->p_sql)
    {
        frfree(p_st_request->p_sql);
        p_st_request->p_sql = NULL;
    }
    /* 释放request metadata */
    frlist_remove_all(&(p_st_request->st_metadata), frdb_metadata_node_free);
    /* 释放bind参数列表 */
    frlist_remove_all(&(p_st_request->st_bind), frdb_field_bind_node_free);
    /* 释放Command列表 */
    frlist_remove_all(&(p_st_request->st_command_lst), db2_cmd_node_free);

    frfree(p_st_request);
    *pp_st_request = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  resposne信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void db2_destroy_response(L7_resp_db2 **pp_st_resp)
{
    if (pp_st_resp == NULL || *pp_st_resp == NULL)
    {
        return;
    }

    L7_resp_db2 *p_st_resp = *pp_st_resp;
    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
        p_st_resp->p_error_msg = NULL;
    }
    frfree(p_st_resp);
    *pp_st_resp = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  取得DDM头部信息
*  ARGS     :  p_st_data(入力bytebuffer)
*           :  p_i_cp(DDM code point)
*           :  p_i_correlator_flg(correlator标识)
*           :  p_ui_ddm_bd_len(DDM body数据长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int db2_get_ddm_hd_info(Frbyte_Packet *p_st_data
                       , int i_whole_flg
                       , int *p_i_cp
                       , int *p_i_correlator_flg
                       , unsigned int *p_ui_ddm_bd_len
                       , int *p_i_exter_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_ddm_id = 0;
    uint16_t u16_cp = 0;
    uint16_t u16_len = 0;
    int i_extended_num = 0;
    uint16_t u16_ddm_len = 0;
    uint32_t u32_extended_len = 0;
    uint64_t u64_extended_len = 0;
    unsigned int ui_extended_len = 0;
    *p_i_exter_flg = DB2_FALSE;

    /* 判断遗留长度是否足够存下一个完整的DDM header */
    if (bytebuff_remaining(p_st_data) < DRDA_DDM_HD_LEN)
    {
        /* 没有后续数据包, 说明解析出错 */
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 取得整个DDM长度(2) */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    /* DDM长度必须大于等于10(DDM header的长度是10) */
    if (i_ret != FR_SUCC || u16_len < DRDA_DDM_HD_LEN)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过DDMID(1) */
    bytebuff_skip(p_st_data, 1);

    /* 取得FORMATID */
    i_ret = bytebuff_get_char(p_st_data, &u8_ddm_id);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设定correlator标识 */
    if (u8_ddm_id & 0x10)
    {
        *p_i_correlator_flg = DB2_TRUE;
    }
    else
    {
        *p_i_correlator_flg = DB2_FALSE;
    }

    /* 跳过RQSDRR(2) */
    bytebuff_skip(p_st_data, 2);
    /* 取得长度位 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_ddm_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得DDM CODE POINT */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_cp, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* Check if this DDM has extended length field */
    if (u16_ddm_len & DB2_CONTINUATION_BIT)
    {
        i_extended_num = u16_ddm_len - DB2_CONTINUATION_BIT - 4;
        if (i_extended_num > bytebuff_remaining(p_st_data))
        {
            /* 没有后续数据包, 说明解析出错 */
            if (i_whole_flg == DB2_TRUE)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                return APM_L7_ANALYZE_TODO;
            }
        }

        switch (i_extended_num)
        {
            case 8:
            case 6:
                i_ret = bytebuff_get_long(p_st_data, i_extended_num
                                         , &u64_extended_len
                                         , BYTE_BIG_ENDIAN);
                ui_extended_len = (unsigned int)u64_extended_len;
                ui_extended_len += 2;
                break;

            case 4:
                i_ret = bytebuff_get_int(p_st_data, i_extended_num
                                        , &u32_extended_len
                                        , BYTE_BIG_ENDIAN);
                ui_extended_len = (unsigned int)u32_extended_len;
                ui_extended_len += 2;
                break;

            case 0:
                if (u16_cp != DRDA_CP_EXTDTA && u16_cp != DRDA_CP_QRYDTA)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_i_exter_flg = DB2_TRUE;
                ui_extended_len = u16_len - DRDA_DDM_HD_LEN;
                break;

            default:
                return APM_L7_ANALYZE_FAIL;

        }

        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u16_ddm_len != u16_len - 6)/* 长度判断 */
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        ui_extended_len = u16_ddm_len - 4;
    }

    /* 设置出力 */
    *p_i_cp = u16_cp;
    /* 因为DDM的总长度位包含DDM header(10), body长度减10 */
    *p_ui_ddm_bd_len = ui_extended_len;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  将当前request command追加到request中
*  ARGS     :  p_st_request(request信息)
*           :  i_req_cmd_cp(当前request command code point)
*           :  l_cursor_id(当前session number)
*           :  i_new_flg(statement是不是新创建的)
*           :  p_st_statement(当前request command的prepare数据索引)
*           :  p_st_resultset(当前request command的cursor ID对应结果集索引)
*           :  p_ccsid(当前Request command的type define)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_add_req_cmd(L7_req_db2 *p_st_request
                   , int i_req_cmd_cp
                   , long l_cursor_id
                   , int i_new_flg
                   , Sql_statement *p_st_statement
                   , Sql_resultset *p_st_resultset)
{
    Db2_req_cmd *p_st_req_cmd = NULL;
    Frlist_node *p_st_node = NULL;

    p_st_req_cmd = (Db2_req_cmd *)frmalloc(sizeof(Db2_req_cmd));
    if (p_st_req_cmd == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_req_cmd->i_error_code = 0;
    p_st_req_cmd->p_error_msg = NULL;
    p_st_req_cmd->i_req_cmd_cp = i_req_cmd_cp;
    p_st_req_cmd->l_cursor_id = l_cursor_id;
    p_st_req_cmd->i_new_flg = i_new_flg;
    p_st_req_cmd->i_close_flg = DB2_FALSE;
    p_st_req_cmd->p_st_statement = p_st_statement;
    p_st_req_cmd->p_st_resultset = p_st_resultset;
    p_st_node = frlist_node_create(p_st_req_cmd);
    if (p_st_node == NULL)
    {
        frfree(p_st_req_cmd);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 追加节点 */
    frlist_push(&p_st_request->st_command_lst, p_st_node);
    /* 设置上一次的command */
    p_st_request->p_st_command_pre = p_st_req_cmd;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得DDM的code point
*  ARGS     :  p_st_fragment(分片包数据信息)
*           :  i_whole_flg(packet是否完整flag)
*           :  p_i_ddm_cp(出力)
*           :  p_ui_ddm_len(ddm总长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_ddm_cp(L7_fragment_db2 *p_st_fragment
                  , int i_whole_flg
                  , int *p_i_ddm_cp
                  , unsigned int *p_ui_ddm_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_correlator_flg = DB2_FALSE;
    unsigned int ui_ddm_db_len = 0;
    int i_exter_flg = DB2_FALSE;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 取得当前DDM的code point */
    if (p_st_fragment->i_req_resp_cp == DRDA_CP_NULL)
    {
        /* 取得DDM header信息 */
        i_ret = db2_get_ddm_hd_info(p_st_data, i_whole_flg, p_i_ddm_cp
                                   , &i_correlator_flg, &ui_ddm_db_len
                                   , &i_exter_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        /* 设置DDM信息 */
        p_st_fragment->i_exter_flg = i_exter_flg;
        p_st_fragment->i_req_resp_cp = *p_i_ddm_cp;
        p_st_fragment->ui_left_ddm_len = ui_ddm_db_len;
        p_st_fragment->i_correlator_flg = i_correlator_flg;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        *p_ui_ddm_len += ui_ddm_db_len + DRDA_DDM_HD_LEN;
    }
    else
    {
        *p_i_ddm_cp = p_st_fragment->i_req_resp_cp;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得COMMAND OBJECT的code point
*  ARGS     :  p_st_fragment(分片包数据信息)
*           :  i_whole_flg(packet是否完整flag)
*           :  p_i_ddm_cp(出力)
*           :  p_ui_ddm_len(ddm总长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_obj_cp(L7_fragment_db2 *p_st_fragment
                  , int i_whole_flg
                  , int *p_i_ddm_cp
                  , unsigned int *p_ui_ddm_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_correlator_flg = DB2_FALSE;
    unsigned int ui_ddm_db_len = 0;
    int i_exter_flg = DB2_FALSE;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 取得当前command object的code point和长度 */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE
        && p_st_fragment->ui_left_obj_len == 0)
    {
        /* 取得DDM header信息 */
        i_ret = db2_get_ddm_hd_info(p_st_data, i_whole_flg, p_i_ddm_cp
                                   , &i_correlator_flg, &ui_ddm_db_len
                                   , &i_exter_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        /* 设置DDM信息 */
        p_st_fragment->i_exter_flg = i_exter_flg;
        p_st_fragment->i_obj_cp = *p_i_ddm_cp;
        p_st_fragment->ui_left_obj_len = ui_ddm_db_len;
        p_st_fragment->i_correlator_flg = i_correlator_flg;
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        *p_ui_ddm_len += ui_ddm_db_len + DRDA_DDM_HD_LEN;
    }
    else if (p_st_fragment->i_obj_cp != DRDA_CP_NULL)
    {
        *p_i_ddm_cp = p_st_fragment->i_obj_cp;
    }
    else
    {
        *p_i_ddm_cp = DRDA_CP_NULL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过DDM
*  ARGS     :  p_st_fragment(分片包信息)
*           :  i_whole_flg(packet完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_skip_ddm(L7_fragment_db2 *p_st_fragment, int i_whole_flg)
{
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    unsigned int ui_ddm_len = p_st_fragment->ui_left_ddm_len;
    unsigned int ui_remaining_len = bytebuff_remaining(p_st_data);

    /* 剩余长度不足 */
    if (ui_remaining_len < ui_ddm_len)
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            /* 设置要跳过的长度 */
            bytebuff_set_skip(p_st_data, ui_ddm_len - ui_remaining_len);
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 跳过当前parameter */
    bytebuff_skip(p_st_data, ui_ddm_len);
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    p_st_fragment->ui_left_ddm_len = 0;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  将EBCDIC装换成ASCII
*  ARGS     :  p_st_data(入力bytebuffer)
*           :  ui_ebcdic_len(EBCDIC数据长度)
*           :  pp_out_ascii(转码之后的ASCII数据)
*           :  p_ui_out_len(出力数据长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data的遗留数据长度必须大于ui_ebcdic_len
*******************************************************************************/
int db2_ebcdic_to_ascii(Frbyte_Packet *p_st_data
                       , unsigned int ui_ebcdic_len
                       , char **pp_out_ascii
                       , unsigned int *p_ui_out_len)
{
    uint8_t u8_one_ebcdic = 0;
    char *p_out_ascii = NULL;

    /* 入力EBCDIC编码数据长度是0 */
    if (ui_ebcdic_len == 0)
    {
        *pp_out_ascii = NULL;
        *p_ui_out_len = 0;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 申请出力buffer */
    p_out_ascii = (char *)frmalloc(ui_ebcdic_len + 1);
    if (p_out_ascii == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_out_ascii[ui_ebcdic_len] = '\0';
    *pp_out_ascii = p_out_ascii;
    *p_ui_out_len = ui_ebcdic_len;

    /* 解析EBCDIC字符串 */
    while (ui_ebcdic_len)
    {
        bytebuff_get_char(p_st_data, &u8_one_ebcdic);
        *p_out_ascii = EBCDIC_TABLE[u8_one_ebcdic];
        p_out_ascii++;
        ui_ebcdic_len--;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  将EBCDIC装换成ASCII
*  ARGS     :  p_st_sess (DB2 session数据)
*           :  p_lst_sess_data (出力session data列表)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_sess必须不为NULL
*******************************************************************************/
int db2_create_session_data(L7session_db2 *p_st_sess
                           , Frlist_header **pp_lst_sess_data)
{
    int i_field_index = 0;
    Frdata_field *p_st_frdata = NULL;
    Frlist_node *p_st_node = NULL;
    Frlist_header *p_lst_sess_data = NULL;

    /* 创建list header */
    p_lst_sess_data = (Frlist_header *)frmalloc(sizeof(Frlist_header));
    if (p_lst_sess_data == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_lst_sess_data, 0x0, sizeof(Frlist_header));

    /* 客户端主机名 */
    if (p_st_sess->p_cli_host_user)
    {
        p_st_frdata = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_frdata == NULL)
        {
            goto error;
        }
        p_st_frdata->em_data_type = FRSTRING;
        p_st_frdata->p_field_name = frstrdup("CLIENT_HOST");
        p_st_frdata->p_field_value = frstrdup(p_st_sess->p_cli_host_user);
        /* 创建list node */
        p_st_node = frlist_node_create(p_st_frdata);
        if (p_st_node == NULL)
        {
            goto error;
        }
        p_st_frdata->i_field_index = ++i_field_index;
        frlist_push(p_lst_sess_data, p_st_node);
        p_st_frdata = NULL;
    }

    /* 客户端的程序名 */
    if (p_st_sess->p_program)
    {
        p_st_frdata = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_frdata == NULL)
        {
            goto error;
        }
        p_st_frdata->em_data_type = FRSTRING;
        p_st_frdata->p_field_name = frstrdup("PROGRAM_NAME");
        p_st_frdata->p_field_value = frstrdup(p_st_sess->p_program);
        /* 创建list node */
        p_st_node = frlist_node_create(p_st_frdata);
        if (p_st_node == NULL)
        {
            goto error;
        }
        p_st_frdata->i_field_index = ++i_field_index;
        frlist_push(p_lst_sess_data, p_st_node);
        p_st_frdata = NULL;
    }

    /* 数据库名 */
    if (p_st_sess->p_db_name)
    {
        p_st_frdata = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_frdata == NULL)
        {
            goto error;
        }
        p_st_frdata->em_data_type = FRSTRING;
        p_st_frdata->p_field_name = frstrdup("DB_NAME");
        p_st_frdata->p_field_value = frstrdup(p_st_sess->p_db_name);
        /* 创建list node */
        p_st_node = frlist_node_create(p_st_frdata);
        if (p_st_node == NULL)
        {
            goto error;
        }
        p_st_frdata->i_field_index = ++i_field_index;
        frlist_push(p_lst_sess_data, p_st_node);
        p_st_frdata = NULL;
    }

    /* 客户端主机名 */
    if (p_st_sess->p_db_user)
    {
        p_st_frdata = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_frdata == NULL)
        {
            goto error;
        }
        p_st_frdata->em_data_type = FRSTRING;
        p_st_frdata->p_field_name = frstrdup("DB_USER");
        p_st_frdata->p_field_value = frstrdup(p_st_sess->p_db_user);
        /* 创建list node */
        p_st_node = frlist_node_create(p_st_frdata);
        if (p_st_node == NULL)
        {
            goto error;
        }
        p_st_frdata->i_field_index = ++i_field_index;
        frlist_push(p_lst_sess_data, p_st_node);
        p_st_frdata = NULL;
    }

    *pp_lst_sess_data = p_lst_sess_data;
    return APM_L7_ANALYZE_SUCC;

error:
    db2_frdata_free(&p_st_frdata);
    frlist_destroy(p_lst_sess_data, db2_frdata_node_free);
    return APM_L7_ANALYZE_FAIL;
}


/*******************************************************************************
*  FUNC     :  根据typdefnam字符串转成对应的int型
*  ARGS     :  p_typdefnam (入力typedefn字符串)
*           :  p_i_typdef (出力力typedefn类型)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_typdef_str2int(char *p_typdefnam, int *p_i_typdef)
{
    if (p_typdefnam == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (strcasecmp(p_typdefnam, "QTDSQL370") == 0)
    {
        *p_i_typdef = DRDA_TYPDEF_QTDSQL370;
    }
    else if (strcasecmp(p_typdefnam, "QTDSQL400") == 0)
    {
        *p_i_typdef = DRDA_TYPDEF_QTDSQL400;
    }
    else if (strcasecmp(p_typdefnam, "QTDSQLX86") == 0)
    {
        *p_i_typdef = DRDA_TYPDEF_QTDSQLX86;
    }
    else if (strcasecmp(p_typdefnam, "QTDSQLASC") == 0)
    {
        *p_i_typdef = DRDA_TYPDEF_QTDSQLASC;
    }
    else if (strcasecmp(p_typdefnam, "QTDSQLVAX") == 0)
    {
        *p_i_typdef = DRDA_TYPDEF_QTDSQLVAX;
    }
    else
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得CHRSTRDR类型数据
*  ARGS     :  p_st_data(入力bytebuffer)
*           :  ui_chrstrdr_len(CHRSTRDR类型数据长度)
*           :  i_whole_flg(packet完整标识)
*           :  p_ccsid(CCSID)
*           :  pp_value(出力CHRSTRDR类型数据)
*           :  p_ui_ddm_left_len(DDM剩余长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_chrstrdr(Frbyte_Packet *p_st_data
                    , unsigned int ui_chrstrdr_len
                    , int i_whole_flg
                    , char *p_ccsid
                    , char **pp_value
                    , unsigned int *p_ui_ddm_left_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned int ui_len = 0;
    char *p_source_data = NULL;

    /* 数据长度为0, 返回NULL */
    if (ui_chrstrdr_len == 0)
    {
        *pp_value = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 实际本次DDM的遗留长度比数据长度还小 */
    if (*p_ui_ddm_left_len < ui_chrstrdr_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 剩余长度不足 */
    if (ui_chrstrdr_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 申请一块存放源数据的内存 */
    p_source_data = (char *)frmalloc(ui_chrstrdr_len + 1);
    if (p_source_data == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得源数据块 */
    i_ret = bytebuff_get_bytes(p_st_data, p_source_data, ui_chrstrdr_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_source_data);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 若CCSID就是UTF-8的就不用做字符转换了 */
    if (strncasecmp(p_ccsid, "UTF-8", 5) == 0)
    {
        p_source_data[ui_chrstrdr_len] = '\0';
        *pp_value = p_source_data;
        *p_ui_ddm_left_len -= ui_chrstrdr_len;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 将参数信息转成UTF-8 */
    i_ret = iconv_to_utf8(p_source_data, ui_chrstrdr_len
                         , p_ccsid, pp_value, &ui_len);
    frfree(p_source_data);
    if (i_ret == 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    *p_ui_ddm_left_len -= ui_chrstrdr_len;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得BINDR类型数据
*  ARGS     :  p_st_data(入力bytebuffer)
*           :  ui_bindr_len(BINDR类型数据长度)
*           :  i_whole_flg(packet完整标识)
*           :  p_i64_value(返回值)
*           :  p_ui_ddm_left_len(DDM剩余长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_bindr(Frbyte_Packet *p_st_data
                 , unsigned int ui_bindr_len
                 , int i_whole_flg
                 , int64_t *p_i64_value
                 , unsigned int *p_ui_ddm_left_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    unsigned int ui_loop = 0;
    int64_t i64_tmp = 0;
    unsigned char arr_str[8] = {0};
    unsigned char arr_value[8] = {0};

    /* int64_t型最大占据8位 */
    if (ui_bindr_len > 8)
    {
        frdbg("Please attention this BINDR value!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 实际本次DDM的遗留长度比数据长度还小 */
    if (*p_ui_ddm_left_len < ui_bindr_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 剩余长度不足 */
    if (ui_bindr_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 取得字符列 */
    i_ret = bytebuff_get_bytes(p_st_data, arr_str, ui_bindr_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 如果是负数 */
    if (arr_str[0] & 0x80)
    {
        while (ui_bindr_len > ui_loop)
        {
            /* 数值位取反 */
            arr_value[ui_loop] = ~arr_str[ui_loop];
            ui_loop++;
        }
    }
    else
    {
        memcpy(arr_value, arr_str, ui_bindr_len);
    }

    /* 取值 */
    ui_loop = 0;
    while (ui_bindr_len > ui_loop)
    {
        i64_tmp = (i64_tmp << 8) + arr_value[ui_loop++];
    }

    /* 如果是负数 */
    if (arr_str[0] & 0x80)
    {
        *p_i64_value = ~i64_tmp;
    }
    else
    {
        *p_i64_value = i64_tmp;
    }

    *p_ui_ddm_left_len -= ui_bindr_len;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得BYTSTRDR类型数据
*  ARGS     :  p_st_data(入力bytebuffer)
*           :  ui_bytstrdr_len(BYTSTRDR类型数据长度)
*           :  i_whole_flg(packet完整标识)
*           :  pp_value(出力CHRSTRDR类型数据)
*           :  p_ui_ddm_left_len(DDM剩余长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_bytstrdr(Frbyte_Packet *p_st_data
                    , unsigned int ui_bytstrdr_len
                    , int i_whole_flg
                    , char **pp_value
                    , unsigned int *p_ui_ddm_left_len)
{
    int i_ret = FR_SUCC;
    unsigned int ui_len = 0;
    uint8_t u8_word = 0;
    uint32_t u32_len = 0;
    char *p_data = NULL;
    char *p_data_tmp = NULL;

    /* 实际本次DDM的遗留长度比数据长度还小 */
    if (*p_ui_ddm_left_len < ui_bytstrdr_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 剩余长度不足 */
    if (ui_bytstrdr_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 申请一块存放源数据的内存 */
    p_data = (char *)frmalloc(ui_bytstrdr_len + 1);
    if (p_data == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_data_tmp = p_data;

    /* 取得源数据块 */
    ui_len = ui_bytstrdr_len;
    while (ui_len)
    {
        i_ret = bytebuff_get_char(p_st_data, &u8_word);
        if (i_ret != FR_SUCC)
        {
            frfree(p_data);
            return APM_L7_ANALYZE_FAIL;
        }
        ui_len--;

        switch (u8_word)
        {
            /* 真实数据开始 */
            case 0x00:
                if (ui_len < 4)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 取得该段数据的长度 */
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC || ui_len < 4  + u32_len)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 取得该段数据的值 */
                i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, u32_len);
                if (i_ret != FR_SUCC)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }
                p_data_tmp[u32_len] = '\0';
                p_data_tmp += u32_len;
                ui_len -= 4 + u32_len;
                break;

            /* 真实数据结束 */
            case 0xFF:
                break;

            default:
                frfree(p_data);
                return APM_L7_ANALYZE_FAIL;
        }
    }

    /* 设置出力 */
    *pp_value = p_data;
    *p_ui_ddm_left_len -= ui_bytstrdr_len;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :
*  ARGS     :  p_st_conn (connect ct)
*           :  p_st_sess (session info)
*  RTN      :  (Mssql_cursor *)
*  NOTE     :
*******************************************************************************/
Frreport_body_data* db2_new_report_body(Conntrack *p_st_conn
                                       , L7session_db2 *p_st_sess)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_sess_body = NULL;

    /* 创建report body */
    p_st_sess_body = frreport_body_new_l7(p_st_conn);
    if (p_st_sess_body == NULL)
    {
        return NULL;
    }
    /* 追加connection相关信息 */
    i_ret = frreport_body_l7_add_connInfo(p_st_sess_body, p_st_conn);
    if (i_ret != FR_SUCC)
    {
        frreport_body_free(&p_st_sess_body);
        return NULL;
    }

    /* add server */
    if (p_st_sess->p_program)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_SERVER
                                         , p_st_sess->p_program);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add username */
    if (p_st_sess->p_db_user)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_USERNAME
                                         , p_st_sess->p_db_user);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add dbname */
    if (p_st_sess->p_db_name)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , DB2_REPORT_KEY_DBNAME
                                         , p_st_sess->p_db_name);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    if (p_st_sess->st_login.tv_sec != 0
        || p_st_sess->st_login.tv_usec != 0)
    {
        /* add request start time */
        i_ret = frreport_body_l7_add_timeval(p_st_sess_body
                                            , APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP
                                            , &p_st_sess->st_login);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }

    return p_st_sess_body;
}
